import ctypes
import enum
from ctypes import c_void_p, c_int, c_uint8, c_int16, c_bool, c_char_p, POINTER, Structure
import datetime

# 加载lib60870库（路径统一配置）
lib60870 = ctypes.CDLL("D:\\Develops\\lib60870-c\\lib60870-C\\python\\lib60870.dll")

# 基础类型定义（主从站共用）
CS101_ASDU = c_void_p
IMasterConnection = c_void_p
CS104_Slave = c_void_p
TLSConfiguration = c_void_p
CS104_APCIParameters = c_void_p
CS101_AppLayerParameters = c_void_p
CS101_SlavePlugin = c_void_p
CP56Time2a = c_void_p  # 与结构体区分，保持指针类型定义
CP16Time2a = c_void_p

# 公共枚举类型
class IEC60870_LinkLayerMode(enum.IntEnum):
    IEC60870_LINK_LAYER_BALANCED = 0
    IEC60870_LINK_LAYER_UNBALANCED = 1

class LinkLayerState(enum.IntEnum):
    LL_STATE_IDLE = 0
    LL_STATE_ERROR = 1
    LL_STATE_BUSY = 2
    LL_STATE_AVAILABLE = 3

class CS104_ServerMode(enum.IntEnum):
    CS104_MODE_SINGLE_REDUNDANCY_GROUP = 0
    CS104_MODE_CONNECTION_IS_REDUNDANCY_GROUP = 1
    CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS = 2

class CS104_PeerConnectionEvent(enum.IntEnum):
    CS104_CON_EVENT_CONNECTION_OPENED = 0
    CS104_CON_EVENT_CONNECTION_CLOSED = 1
    CS104_CON_EVENT_EVENT_ACTIVATED = 2
    CS104_CON_EVENT_DEACTIVATED = 3

class CS104_ConnectionEvent(enum.IntEnum):
    CONNECTION_OPENED = 0
    CONNECTION_CLOSED = 1
    STARTDT_CON_RECEIVED = 2
    STOPDT_CON_RECEIVED = 3
    CONNECTION_FAILED = 4

class IEC60870_5_TypeID(enum.IntEnum):
    M_SP_NA_1 = 1
    M_SP_TA_1 = 2
    M_DP_NA_1 = 3
    # ... 其他类型ID，根据iec60870_common.h补充
    F_SC_NB_1 = 127

class CS101_CauseOfTransmission(enum.IntEnum):
    PERIODIC = 1
    BACKGROUND_SCAN = 2
    SPONTANEOUS = 3
    INITIALIZED = 4
    REQUEST = 5
    ACTIVATION = 6
    ACTIVATION_CON = 7
    DEACTIVATION = 8
    DEACTIVATION_CON = 9
    ACTIVATION_TERM = 10
    RETURN_INFO_REMOTE = 11
    RETURN_INFO_LOCAL = 12
    FILE_TRANSFER = 13
    # ... 其他传输原因，根据iec60870_common.h补充
    INTERROGATED_BY_STATION = 20
    INTERROGATED_BY_GROUP_0 = 21
    INTERROGATED_BY_GROUP_1 = 22
    INTERROGATED_BY_GROUP_2 = 23
    INTERROGATED_BY_GROUP_3 = 24
    INTERROGATED_BY_GROUP_4 = 25
    INTERROGATED_BY_GROUP_5 = 26
    INTERROGATED_BY_GROUP_6 = 27
    INTERROGATED_BY_GROUP_7 = 28
    INTERROGATED_BY_GROUP_8 = 29
    INTERROGATED_BY_GROUP_9 = 30
    INTERROGATED_BY_GROUP_10 = 31
    INTERROGATED_BY_GROUP_11 = 32
    INTERROGATED_BY_GROUP_12 = 33
    INTERROGATED_BY_GROUP_13 = 34
    INTERROGATED_BY_GROUP_14 = 35
    INTERROGATED_BY_GROUP_15 = 36
    INTERROGATED_BY_GROUP_16 = 37
    
    UNKNOWN_IOA = 47

class QualifierOfInterrogation(enum.IntEnum):
    STATION_INTERROGATION = 20
    GROUP_1 = 1
    GROUP_2 = 2
    GROUP_3 = 3
    GROUP_4 = 4
    GROUP_5 = 5
    GROUP_6 = 6
    GROUP_7 = 7
    GROUP_8 = 8
    GROUP_9 = 9
    GROUP_10 = 10
    GROUP_11 = 11
    GROUP_12 = 12
    GROUP_13 = 13
    GROUP_14 = 14
    GROUP_15 = 15
    CLEAR = 0

# 公共结构体定义
class Lib60870VersionInfo(Structure):
    _fields_ = [
        ("major", c_int),
        ("minor", c_int),
        ("patch", c_int)
    ]

class CP56Time2aStruct(Structure):
    """CP56Time2a时间结构体（用于数据传输）"""
    _fields_ = [
        ("milliseconds", ctypes.c_uint16),
        ("minutes", ctypes.c_uint8),
        ("hours", ctypes.c_uint8),
        ("day", ctypes.c_uint8),
        ("month", ctypes.c_uint8),
        ("year", ctypes.c_uint8),
        ("is_valid", ctypes.c_uint8, 1),
        ("summer_time", ctypes.c_uint8, 2)
    ]

    @classmethod
    def from_datetime(cls, dt: datetime.datetime):
        """从datetime对象创建CP56Time2aStruct"""
        obj = cls()
        obj.milliseconds = dt.microsecond // 1000
        obj.minutes = dt.minute
        obj.hours = dt.hour
        obj.day = dt.day
        obj.month = dt.month
        obj.year = dt.year % 100  # 只取后两位
        obj.is_valid = 1
        obj.summer_time = 0
        return obj

class sCS101_AppLayerParameters(Structure):
    _fields_ = [
        ("sizeOfTypeId", c_int),
        ("sizeOfVSQ", c_int),
        ("sizeOfCOT", c_int),
        ("originatorAddress", c_int),
        ("sizeOfCA", c_int),
        ("sizeOfIOA", c_int),
        ("maxSizeOfASDU", c_int)
    ]

class sCS104_APCIParameters(Structure):
    _fields_ = [
        ("k", c_int),
        ("w", c_int),
        ("t0", c_int),
        ("t1", c_int),
        ("t2", c_int),
        ("t3", c_int)
    ]

class sLinkLayerParameters(Structure):
    _fields_ = [
        ("addressLength", c_int),
        ("timeoutForAck", c_int),
        ("timeoutRepeat", c_int),
        ("useSingleCharACK", c_bool),
        ("timeoutLinkState", c_int)
    ]

# 公共回调函数类型定义
IEC60870_LinkLayerStateChangedHandler = ctypes.CFUNCTYPE(
    None, c_void_p, c_int, c_int)  # 参数: parameter, address, newState

IEC60870_RawMessageHandler = ctypes.CFUNCTYPE(
    None, c_void_p, POINTER(c_uint8), c_int, c_bool)  # 参数: parameter, msg, msgSize, sent

CS101_InterrogationHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, IMasterConnection, CS101_ASDU, c_uint8)  # 参数: parameter, connection, asdu, qoi

CS101_ASDUHandler = ctypes.CFUNCTYPE(
    None, c_void_p, IMasterConnection, CS101_ASDU)

CS101_ClockSynchronizationHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, IMasterConnection, CS101_ASDU, CP56Time2a)  # 参数: parameter, connection, asdu, newTime

CS104_ConnectionRequestHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, c_char_p)  # 参数: parameter, ipAddress

CS104_ConnectionEventHandler = ctypes.CFUNCTYPE(
    None, c_void_p, IMasterConnection, c_int)  # 参数: parameter, connection, event

ASDUReceivedHandler = ctypes.CFUNCTYPE(
    None, ctypes.c_void_p, ctypes.c_void_p)  # 参数: parameter, CS101_ASDU

# 公共函数封装（iec60870_common.h）
lib60870.Lib60870_getLibraryVersionInfo.restype = Lib60870VersionInfo
lib60870.Lib60870_getLibraryVersionInfo.argtypes = []

lib60870.CS101_ASDU_getTypeID.restype = c_int
lib60870.CS101_ASDU_getTypeID.argtypes = [CS101_ASDU]

lib60870.CS101_ASDU_getCOT.restype = c_int
lib60870.CS101_ASDU_getCOT.argtypes = [CS101_ASDU]

lib60870.CS101_ASDU_getCA.restype = c_int
lib60870.CS101_ASDU_getCA.argtypes = [CS101_ASDU]

# 信息对象相关函数封装
lib60870.MeasuredValueScaled_create.restype = c_void_p  # 返回InformationObject
lib60870.MeasuredValueScaled_create.argtypes = [c_void_p, c_int, c_int16, c_int]  # 前一个对象, IOA, 值, 质量

lib60870.SinglePointInformation_create.restype = c_void_p  # 返回InformationObject
lib60870.SinglePointInformation_create.argtypes = [c_void_p, c_int, c_bool, c_int]  # 前一个对象, IOA, 状态, 质量

lib60870.InformationObject_destroy.restype = None
lib60870.InformationObject_destroy.argtypes = [c_void_p]  # InformationObject

# ASDU相关函数封装
lib60870.CS101_ASDU_create.restype = CS101_ASDU
lib60870.CS101_ASDU_create.argtypes = [
    CS101_AppLayerParameters,  # 应用层参数
    c_bool,                    # 带时间戳?
    c_int,                     # 传输原因(COT)
    c_int,                     # 公共地址(CA)
    c_int,                     # 信息对象地址(IOA)
    c_bool,                    # 是序列?
    c_bool                     # 测试模式?
]

lib60870.CS101_ASDU_addInformationObject.restype = c_bool
lib60870.CS101_ASDU_addInformationObject.argtypes = [CS101_ASDU, c_void_p]  # ASDU, InformationObject

lib60870.CS101_ASDU_destroy.restype = None
lib60870.CS101_ASDU_destroy.argtypes = [CS101_ASDU]

# 获取应用层参数函数
lib60870.IMasterConnection_getApplicationLayerParameters.restype = CS101_AppLayerParameters
lib60870.IMasterConnection_getApplicationLayerParameters.argtypes = [IMasterConnection]

# 发送ACT_TERM确认
lib60870.IMasterConnection_sendACT_TERM.restype = c_bool
lib60870.IMasterConnection_sendACT_TERM.argtypes = [IMasterConnection, CS101_ASDU]